﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Corecalc
{
    class CellAreaRemover
    {
        public static List<CellAreaNode> Cans = new List<CellAreaNode>();

        public static void RemoveFromGraph() {
            foreach (CellAreaNode can in Cans) {
                can.RemoveFromGraph();
            }
        }

        public static void AddToCellAreaNodes(CellAreaNode can) {
            Cans.Add(can);
        }
    }

    class MPModel
    {
        public static double TMin = 0.0;

        //Multiprocessor model
        public static double TSched = 10.0;   //100 cycles
        public static double cyclesToReadOneByte = 0.0000000001;
        public static double cyclesToWriteOneByte = 0.0000000001;
        public static int ProcessorCount = 8;

        public static readonly Func<double, double> Rc = bytes => cyclesToReadOneByte * bytes;    //Read communication overhead (bytes -> cycles)
        public static readonly Func<double, double> Wc = bytes => cyclesToWriteOneByte * bytes;   //Write communication overhead (bytes -> cycles)

        private static Dictionary<string, int> communicationCosts = new Dictionary<string, int> {
            { "int", 4 },
            { "double", 8 },
            { "bool", 1 },
            { "char", 1 }
        };

        private static Dictionary<string, double> simpleExecutionTimeCosts = new Dictionary<string, double> {
            { "+", 2.0 },
            { "-", 2.0 },
            { "/", 2.0 },         //Division may be 22 times larger than add, sub, ...
            { "*", 2.0 },
            { ">", 2.0 },
            { "<", 2.0 },
            { ">=", 2.0 },
            { "<=", 2.0 },
            { "&", 2.0 },
            { "<>", 2.0 },
            { "=", 2.0 },
            { "COS", 5 },
            { "SIN", 5 },
            { "TAN", 5 },
            { "SQRT", 5 },
            { "const", 0.5 },
            { "cellref", 0.5 }
        };

        public static int FromTextValue(string value) {
            return communicationCosts["char"] * value.Length;
        }

        public static double GetExecutionTime(string op) {
            return simpleExecutionTimeCosts[op];
        }

        public static int GetCommunicationCost(string type) {
            return communicationCosts[type];
        }

        public static double GetCommunicationCost(FullCellAddr fca) {
            Cell cell = fca.sheet[fca.ca];
            return GetCommunicationCost(cell, fca);
        }

        public static double GetCommunicationCost(Cell cell, FullCellAddr fca) {
            if (cell is NumberCell) {
                return GetCommunicationCost("double");
            } else if (cell is TextCell) {
                TextCell txtCell = cell as TextCell;
                return txtCell.value.CommunicationCost;
            } else if (cell is BlankCell) {
                return 0;
            } else {
                Formula formula = cell as Formula;
                return formula.CommunicationCost(fca);
            }
        }
    }
}
